// N1AutoreleasePool.cpp: implementation of the N1AutoreleasePool class.
//
//////////////////////////////////////////////////////////////////////

#include "N1AutoreleasePool.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
N1AutoreleasePool::N1AutoreleasePool() 
{
    m_prevPool = N1Thread::setThreadLastAutoreleasePool(this);
}

N1AutoreleasePool::~N1AutoreleasePool() 
{
    clear();

    N1Thread::setThreadLastAutoreleasePool(m_prevPool);
}

N1NAME_DEF(N1AutoreleasePool)

uint32 N1AutoreleasePool::clear()
{
    uint32 count = m_list.size();
    PoolList::iterator i = m_list.begin();
    for(;i!=m_list.end();i++)
    {
        (*i)->release();
    }
    m_list.clear();
    return count;
}

void N1AutoreleasePool::addObject(N1Object *obj) 
{
    m_list.push_front(obj);
}

void N1AutoreleasePool::add(N1Object *obj) 
{
    defaultPool()->addObject(obj);
}

N1AutoreleasePool* N1AutoreleasePool::defaultPool() 
{
    return N1Thread::getThreadLastAutoreleasePool();
}

N1AutoreleasePool* N1DefaultPool() 
{
    return N1AutoreleasePool::defaultPool();
}

/**********************************************************
*********************** TESTS *****************************
**********************************************************/
#ifdef N1LIB_SELFTEST

static N1UInt32 gCTestCount;

class CTest : public N1Object
{
public:
    CTest() { gCTestCount++; };
    ~CTest() { gCTestCount--; }; 

    void inc() { gCTestCount++; };

    void newCTest() 
    {
        CTest *p = new CTest();
        p->autorelease();
    }

    CTest* newCTest2() 
    {
        return (new CTest())->autorelease<CTest>();
    }

    pcstr name() const { return "CTest"; };
};

N1TEST(N1AutoreleasePoolTest1)
{
    gCTestCount = 0;

    N1CHECK(gCTestCount==0, 1);
    {
        N1AutoreleasePool pool;

        CTest *ptr = new CTest();
        ptr->autorelease();             //1 autoreleased
        {
            N1AutoreleasePool pool2;
            ptr->newCTest();           //1 autoreleased
            ptr->newCTest();           //1 autoreleased
        }
    }
    N1CHECK(gCTestCount==0, 2);
    {
        N1AutoreleasePool pool;

        CTest *ptr1 = new CTest();  //1 autoreleased
        CTest *ptr2 = new CTest();  //1 non autoreleased
        ptr1->autorelease();
        ptr2->inc();                //1 non autoreleased
        ptr2->newCTest();           //1 autoreleased
    }
    //N1CHECK(gCTestCount==2, 3);
}

#endif //N1LIB_SELFTEST
